use std::collections::VecDeque;

use super::*;

#[repr(u8)]
#[derive(PartialEq)]
enum RepeatStatus {
    Active,
    Waiting,
    Finished,
}

impl RepeatStatus {
    fn is_active(&self) -> bool {
        RepeatStatus::Active == *self
    }

    fn is_waiting(&self) -> bool {
        RepeatStatus::Waiting == *self
    }

    fn is_finished(&self) -> bool {
        RepeatStatus::Finished == *self
    }
}

pub struct Repeat {
    status: RepeatStatus,
    exit: Box<dyn ICondition>,
    children: VecDeque<Box<dyn ITask>>,
}

impl Repeat {
    pub fn new<It>(children: It, exit: Box<dyn ICondition>) -> Box<Self> where It: IntoIterator<Item = Box<dyn ITask>> {
        Box::new(Self {
            status: RepeatStatus::Active,
            exit,
            children: children.into_iter().collect(),
        })
    }

    pub fn push_child(&mut self, child: Box<dyn ITask>) {
        self.children.push_back(child);
    }
}

impl ITask for Repeat {
    fn step(&mut self) {
        if self.exit.check() {
            self.status = RepeatStatus::Waiting;
        }

        if let Some(task) = self.children.front_mut() {
            task.step();
            
            if task.is_finished() {
                if self.status.is_active() {
                    let mut task = self.children.pop_front().unwrap();
                    task.reset();
                    self.children.push_back(task);
                } else if self.status.is_waiting() {
                    self.status = RepeatStatus::Finished;
                }
            }
            
        }
    }

    fn reset(&mut self) {
        self.status = RepeatStatus::Active;
        self.exit.reset();
        for task in self.children.iter_mut() {
            task.reset();
        }
    }

    fn is_finished(&self) -> bool {
        self.status.is_finished()
    }
}

